package com.gateway.video.rtsp.server.transport.rtp.handler;

import com.gateway.video.rtsp.server.transport.rtp.codec.RtpPacket;
import com.gateway.video.rtsp.stream.h264.H264VideoStream;
import com.gateway.video.rtsp.stream.pull.PullSource;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.socket.DatagramPacket;
import lombok.extern.slf4j.Slf4j;
import lombok.var;
import org.springframework.beans.factory.annotation.Autowired;
import sun.security.provider.MD5;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.time.LocalDateTime;
import java.time.ZoneId;

import static org.bytedeco.javacpp.avcodec.av_packet_unref;

@Slf4j
public class RtpServerHandler extends ChannelInboundHandlerAdapter {
    @Autowired
    private H264VideoStream h264VideoStream;

    private short seq;

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        super.channelActive(ctx);
        ctx.read();
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        var packet = (DatagramPacket) msg;
        var readableBytes = packet.content().readableBytes();

        if (readableBytes > 0) {
            /* 解析视频流推送到该地址 */
            var sender = packet.sender();

            var grabber = PullSource.getInstance().grabber;

            long errCount = 0;
            try {
                var avPacket = grabber.grabPacket();
                if (avPacket == null || avPacket.size() <= 0 || avPacket.data() == null) {
                    if (log.isWarnEnabled()) {
                        log.warn("Video server miss pack number: {}");
                    }
                    ctx.read();
                    return;
                }

                long toEpochMilli = LocalDateTime.now().atZone(ZoneId.of("+8")).toInstant().toEpochMilli();
                RtpPacket rtpPacket = new RtpPacket(false);
                rtpPacket.wrap(false, 96, seq++, toEpochMilli, MD5.class.hashCode(), avPacket.data().getStringBytes(), (int) avPacket.position(), avPacket.size() - 1);
                ByteBuffer buffer = rtpPacket.getBuffer();
                ByteBuf byteBuf = Unpooled.copiedBuffer(buffer);
                ChannelFuture channelFuture = ctx.writeAndFlush(new DatagramPacket(byteBuf, sender)).addListener(future -> {
                    if (future.isSuccess()) {
                        log.debug("send success");
                    } else {
                        if (log.isErrorEnabled()) {
                            log.error("send fail");
                        }
                    }
                });

                av_packet_unref(avPacket);
            } catch (IOException e) {
                if (log.isWarnEnabled()) {
                    log.warn("Video server send packet fail, err_index:{}", errCount);
                }
                ctx.read();
            }
        }

        ctx.read();
    }
}
